#pragma once

#include "SamplerState.hpp"
#include "D3D11Declarations.hpp"




namespace Engine
{
	namespace Video
	{
		class D3D11SamplerState
			: public SamplerState
		{
		public:

			SHARED(D3D11SamplerState);
			typedef boost::function<void (weak_ptr)>   notify;

		protected:

			D3D11SamplerState(const notify& destroyedFn, const ID3D11DevicePtr& device);
			void post_create(ptr _this);

		public:

			MAKE_SHARED2(D3D11SamplerState, notify, ID3D11DevicePtr);
			~D3D11SamplerState();



			/**
			 * Applies the sampler state (ie. creates/updates it when required)
			 * and then returns a pointer to the D3D11 interface to set it to the pipeline.
			 */
			const ID3D11SamplerStatePtr& apply();



			void setFilter(Filter::Type filter);
			void setAddressU(Address::Type address);
			void setAddressV(Address::Type address);
			void setAddressW(Address::Type address);
			void setMipLODBias(float bias);
			void setMaxAnisotropy(uint32 max);
			void setComparisonFunc(Comparison::Type func);
			void setMinLOD(float min);
			void setMaxLOD(float max);
			void setBorderColor(const float4& color);



			Filter::Type filter() const;
			Address::Type addressU() const;
			Address::Type addressV() const;
			Address::Type addressW() const;
			float mipLODBias() const;
			uint32 maxAnisotropy() const;
			Comparison::Type comparisonFunc() const;
			float minLOD() const;
			float maxLOD() const;
			float4 borderColor() const;

		private:

			void updateState();
			D3D11_SAMPLER_DESC createDesc() const;
			static D3D11_FILTER filter(Filter::Type filter);
			static D3D11_TEXTURE_ADDRESS_MODE Address(Address::Type address);
			static D3D11_COMPARISON_FUNC D3D11SamplerState::comparisonFunc(Comparison::Type func);

		private:

			weak_ptr                m_this;
			notify                  m_destroyed;
			ID3D11DevicePtr         m_device;
			ID3D11SamplerStatePtr   m_samplerState;


			/// This flag indicates if the values have changed and thus the
			/// sampler state should be recreated
			bool                    m_changed;

			Filter::Type            m_filterType;
			Address::Type           m_addressU;
			Address::Type           m_addressV;
			Address::Type           m_addressW;
			float                   m_mipLODBias;

			// "Clamping value used if D3D11_FILTER_ANISOTROPIC or D3D11_FILTER_COMPARISON_ANISOTROPIC is specified in Filter.
			// Valid values are between 1 and 16"
			uint32                  m_maxAnisotropy;
			Comparison::Type        m_comparisonFunc;
			float                   m_minLOD;
			float                   m_maxLOD;
			float4                  m_borderColor;
		};
		///////////////////////////////////////////////////////////////////////////////////////////
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
